"""
General constant string used in bqpystra.
"""

from enum import Enum
import pandas as pd
from datetime import timedelta

# region 常量
# 默认空值
EMPTY_STRING = ''
EMPTY_UNICODE = ''
EMPTY_INT = 0
EMPTY_FLOAT = 0.0
# # ctp redis 中数据库
COMMONDB = 0  # 通用数据库
QUOTEDB = 1  # 市场行情数据库
TRADEDB = 2  # 交易数据库
ACCOUNTDB = 10  # 账户数据库
STRATEGYDB = 3  # 策略数据库
# GATEWAY
GATEWAY_CTP = 'CTP'  # CTP
GATEWAY_TQ = 'TQ'  # 天勤
GATEWAY_HF = 'HF'  # 海风
GATEWAY_CTP_TD = 'CTPTD'  # CTP
GATEWAY_TQ_TD = 'TQTD'  # 天勤
GATEWAY_HF_TD = 'HFTD'  # 海风
GATEWAY_CTP_QT = 'CTPQT'  # CTP
GATEWAY_TQ_QT = 'TQQT'  # 天勤
GATEWAY_HF_QT = 'HFQT'  # 海风

# 方向常量
DIRECTION_NONE = '无方向'
DIRECTION_LONG = '买'
DIRECTION_SHORT = '卖'
DIRECTION_UNKNOWN = '未知'
DIRECTION_NET = '净'
DIRECTION_SELL = '卖出'  # IB接口
EN_DIRECTION_NONE = 'No'
EN_DIRECTION_LONG = 'Buy'
EN_DIRECTION_SHORT = 'Sell'
EN_DIRECTION_UNKNOWN = 'Unknown'
EN_DIRECTION_NET = 'Net'
EN_DIRECTION_SELL = 'Sell'  # IB接口
CTP_DIRECTION_LONG = 0  # ord('0')
CTP_DIRECTION_SHORT = 1  # ord('1')
CTP_DIRECTION_BUY = 0  # ord('0')
CTP_DIRECTION_SELL = 1  # ord('1')

# 开平常量
OFFSET_NONE = '未知'
OFFSET_OPEN = '开仓'
OFFSET_CLOSE = '平仓'
OFFSET_CLOSETODAY = '平今'
OFFSET_CLOSEYESTERDAY = '平昨'
OFFSET_UNKNOWN = '未知'
EN_OFFSET_NONE = 'No'
EN_OFFSET_OPEN = 'Open'
EN_OFFSET_CLOSE = 'Close'
EN_OFFSET_CLOSETODAY = 'CloseToday'
EN_OFFSET_CLOSEYESTERDAY = 'CloseYesterday'
EN_OFFSET_UNKNOWN = 'Unknown'
CTP_OFFSET_OPEN = 0  # ord('0')
CTP_OFFSET_CLOSE = 1  # ord('1')
CTP_OFFSET_CLOSETODAY = 3  # ord('3')
CTP_OFFSET_CLOSEYESTERDAY = 4  # ord('4')

POSITION_LONG = 0  # ord('0')
POSITION_SHORT = 1  # ord('1')
POSITION_OPEN = 0  # ord('0')
POSITION_CLOSE = 1  # ord('1')
POSITION_CLOSETODAY = 3  # ord('3')
POSITION_CLOSEYESTERDAY = 4  # ord('4')
# 天勤交易常量
TQ_OFFSET_OPEN = 'OPEN'
TQ_OFFSET_CLOSE = 'CLOSE'
TQ_OFFSET_CLOSETODAY = 'CLOSETODAY'
TQ_DIRECTION_LONG = 'BUY'
TQ_DIRECTION_SHORT = 'SELL'
TQ_DIRECTION_BUY = 'BUY'
TQ_DIRECTION_SELL = 'SELL'
# 交易信号常量
TRADE_SIGNAL_NONE = '无'
TRADE_SIGNAL_OPENLONG = '开多'
TRADE_SIGNAL_CLOSELONG = '平多'
TRADE_SIGNAL_OPENSHORT = '开空'
TRADE_SIGNAL_CLOSESHORT = '平空'
TRADE_SIGNAL_BUY = '开多'
TRADE_SIGNAL_SELL = '平多'
TRADE_SIGNAL_SHORT = '开空'
TRADE_SIGNAL_COVER = '平空'
# 交易信号方向常量
TRADE_SIGNAL_DIRECTION_LONG = '做多'
TRADE_SIGNAL_DIRECTION_SHORT = '做空'
TRADE_SIGNAL_DIRECTION_BOTH = '双向'
# 状态常量
STATUS_NOTTRADED = '未成交'
STATUS_PARTTRADED = '部分成交'
STATUS_ALLTRADED = '全部成交'
STATUS_CANCELLED = '已撤销'
STATUS_UNKNOWN = '未知'

CTP_STATUS_ALLTRADED = ord('0')
CTP_STATUS_PARTTRADEDQUEUEING = ord('1')
CTP_STATUS_PARTTRADEDNOTQUEUEING = ord('2')
CTP_STATUS_NOTRADEDQUEUEING = ord('3')
CTP_STATUS_NOTRADEDNOTQUEUEING = ord('4')
CTP_STATUS_CANCELLED = ord('5')
CTP_STATUS_UNKNOWN = ord('a')

# 合约类型常量
PRODUCT_EQUITY = '股票'
PRODUCT_FUTURES = '期货'
PRODUCT_OPTION = '期权'
PRODUCT_INDEX = '指数'
PRODUCT_COMBINATION = '组合'
PRODUCT_FOREX = '外汇'
PRODUCT_UNKNOWN = '未知'
PRODUCT_SPOT = '现货'
PRODUCT_DEFER = '延期'
PRODUCT_NONE = ''
CONTRACT_MAIN = '0000'  # 主力合约
CONTRACT_SECOND = '1111'  # 次主力合约
CONTRACT_OTHER = '9999'  # 其它

# 价格类型常量
PRICETYPE_LIMITPRICE = '限价'
PRICETYPE_MARKETPRICE = '市价'
PRICETYPE_FAK = 'FAK'
PRICETYPE_FOK = 'FOK'

# 期权类型
OPTION_CALL = '看涨期权'
OPTION_PUT = '看跌期权'

# 交易所类型
EXCHANGE_SHSE = 'SHSE'  # 上交所
EXCHANGE_SZSE = 'SZSE'  # 深交所
EXCHANGE_CFFEX = 'CFFEX'  # 中金所
EXCHANGE_SHFE = 'SHFE'  # 上期所
EXCHANGE_CZCE = 'CZCE'  # 郑商所
EXCHANGE_DCE = 'DCE'  # 大商所
EXCHANGE_SGE = 'SGE'  # 上金所
EXCHANGE_INE = 'INE'  # 上期能源
EXCHANGE_FUTURE = [EXCHANGE_CFFEX, EXCHANGE_SHFE, EXCHANGE_CZCE,
                   EXCHANGE_DCE, EXCHANGE_INE]  # 期货交易所
EXCHANGE_STOCK = [EXCHANGE_SHSE, EXCHANGE_SZSE]  # 股票交易所
EXCHANGE = [EXCHANGE_SHSE, EXCHANGE_SZSE, EXCHANGE_CFFEX,
            EXCHANGE_SHFE, EXCHANGE_CZCE, EXCHANGE_DCE]
EXCHANGE_YT = [EXCHANGE_SHFE]  # 区分平昨、平今的交易所列表
EXCHANGE_UNKNOWN = 'UNKNOWN'  # 未知交易所
EXCHANGE_NONE = ''  # 空交易所
EXCHANGE_HKEX = 'HKEX'  # 港交所

EXCHANGE_SMART = 'SMART'  # IB智能路由（股票、期权）
EXCHANGE_NYMEX = 'NYMEX'  # IB 期货
EXCHANGE_GLOBEX = 'GLOBEX'  # CME电子交易平台
EXCHANGE_IDEALPRO = 'IDEALPRO'  # IB外汇ECN

EXCHANGE_OANDA = 'OANDA'  # OANDA外汇做市商
EXCHANGE_OKCOIN = 'OKCOIN'  # OKCOIN比特币交易所

# 货币类型
CURRENCY_USD = 'USD'  # 美元
CURRENCY_CNY = 'CNY'  # 人民币
CURRENCY_UNKNOWN = 'UNKNOWN'  # 未知货币
CURRENCY_NONE = ''  # 空货币
# 行情及交易协议类型
PROTOCOL_CTP = 'CTP'
PROTOCOL_STOCK = 'STOCK'

# 趋势类型
TREND_UP = 1
TREND_DOWN = -1
TREND_NONE = 0
# 某根K线所处位置分类
TREND_POSITION_BALANCE_START = 0b001000000  # 均衡状态开始
TREND_POSITION_BALANCE_OK = 0b010000000  # 均衡状态确认
TREND_POSITION_BALANCE = 0b011000000  # 均衡状态持续
TREND_POSITION_BALANCE_END = 0b111000000  # 均衡状态结束
TREND_POSITION_UP_START = 0b000001000  # 上涨开始
TREND_POSITION_UP_OK = 0b000010000  # 上涨确认
TREND_POSITION_UP = 0b000011000  # 上涨持续
TREND_POSITION_UP_END = 0b000111000  # 上涨结束
TREND_POSITION_DOWN_START = 0b000000001  # 下跌开始
TREND_POSITION_DOWN_OK = 0b000000010  # 下跌确认
TREND_POSITION_DOWN = 0b000000011  # 下跌持续
TREND_POSITION_DOWN_END = 0b000000111  # 下跌结束
TREND_POSITION_NONE = 0b000000000  # 未知

# 策略或指标用周期类型
PERIOD_TYPE_TICK = 0
PERIOD_TYPE_M1 = 1 * 60
PERIOD_TYPE_M3 = 3 * 60
PERIOD_TYPE_M5 = 5 * 60
PERIOD_TYPE_M10 = 10 * 60
PERIOD_TYPE_M15 = 15 * 60
PERIOD_TYPE_M30 = 30 * 60
PERIOD_TYPE_H1 = 60 * 60
PERIOD_TYPE_DAY = 60 * 60 * 24
PERIOD_TYPE_WEEK = 7 * 24 * 60 * 60
PERIOD_TYPE_MONTH = 60 * 60 * 24 * 30
PERIOD_TYPE_YEAR = 60 * 60 * 24 * 365

period_en_zh_dict = {
    "TICK": "分时",
    "M1": "1分钟",
    "M3": "3分钟",
    "M5": "5分钟",
    "M10": "10分钟",
    "M15": "15分钟",
    "M30": "30分钟",
    "H1": "1小时",
    "DAY": "日",
    "WEEK": "周",
    "MONTH": "月",
    "YEAR": "年"
}
period_zh_en_dict = {v: k for k, v in period_en_zh_dict.items()}
period_en_value_dict = {
    "TICK": PERIOD_TYPE_TICK,
    "M1": PERIOD_TYPE_M1,
    "M3": PERIOD_TYPE_M3,
    "M5": PERIOD_TYPE_M5,
    "M10": PERIOD_TYPE_M10,
    "M15": PERIOD_TYPE_M15,
    "M30": PERIOD_TYPE_M30,
    "H1": PERIOD_TYPE_H1,
    "DAY": PERIOD_TYPE_DAY,
    "WEEK": PERIOD_TYPE_WEEK,
    "MONTH": PERIOD_TYPE_MONTH,
    "YEAR": PERIOD_TYPE_YEAR
}
period_zh_value_dict = {k: period_en_value_dict[v] for k, v in period_zh_en_dict.items()}

future_exchange_dict = {'CFFEX': '中金所', 'DCE': '大期所', 'CZCE': '郑期所', 'SHFE': '上期所', 'INE': '能源所',
                        'SSFuture': '自选', 'MainFuture': '主力', 'TradingFuture': '交易', }
stock_exchange_dict = {'SSStock': '自选股票', 'SZSE': '深交所', 'SSE': '上交所'}

# CTA引擎中涉及到的交易方向类型
STRATEGY_ORDER_NONE = 'UN'
STRATEGY_ORDER_BUY = '买开'  # 开多
STRATEGY_ORDER_SELL = '卖平'  # 平多
STRATEGY_ORDER_SHORT = '卖开'  # 开空
STRATEGY_ORDER_COVER = '买平'  # 平空
STRATEGY_ORDER_COVER_BUY = '平空开多'
STRATEGY_ORDER_SELL_SHORT = '平多开空'
strategy_order_type = {
    STRATEGY_ORDER_BUY: 1,
    STRATEGY_ORDER_SELL: -1,
    STRATEGY_ORDER_SHORT: -2,
    STRATEGY_ORDER_COVER: 2,
    STRATEGY_ORDER_COVER_BUY: 4,
    STRATEGY_ORDER_SELL_SHORT: -4
}

STRATEGY_SIGNAL_OFFSET_NONE = 'UN'
STRATEGY_SIGNAL_OFFSET_OPEN = '开'
STRATEGY_SIGNAL_OFFSET_CLOSE = '平'
STRATEGY_SIGNAL_OFFSET_STOPLOSS = '止损'
STRATEGY_SIGNAL_DIRECTION_LONG = '多'
STRATEGY_SIGNAL_DIRECTION_SHORT = '空'
STRATEGY_SIGNAL_DIRECTION_NONE = 'UN'
stra_bssc_zh_zh_dict = {}
# 本地停止单状态
STOPORDER_WAITING = '等待中'
STOPORDER_CANCELLED = '已撤销'
STOPORDER_TRIGGERED = '已触发'

# 本地停止单前缀
STOPORDERPREFIX = 'CtaStopOrder.'

# 数据库名称
DBTYPE_SQLITE = 'SQLITE'
DBTYPE_MONGODB = 'MONGODB'
SETTING_DB_NAME = 'Trader_Setting_Db'
TICK_DB_NAME = 'Trader_Tick_Db'
DAILY_DB_NAME = 'Trader_Daily_Db'
MINUTE_DB_NAME = 'CTP_Min_Db'
STRATEGY_DB_NAME = 'Strategy_Db'
STRATEGY_TEST_DB_NAME = 'Strategy_Test_Db'
STRATEGY_TEST_ORDER_TABLE_NAME = 'Strategy_Test_'  # 策略测试结果表，后跟策略名称
STRATEGY_TABLE_NAME = 'Strategies'
STRATEGY_PARAMS_DB_NAME = 'Strategy_Db'

SQLITEDB_STRATEGY_NAME = 'strategtDB'
SQLITEDB_HISTORY_NAME = 'quoteDB'

# 引擎类型，用于区分当前策略的运行环境
ENGINETYPE_BACKTESTING = 'backtesting'  # 回测
ENGINETYPE_TESTING = 'testing'  # 测试 在实盘环境中跑，但不与实际账户连接,只记录交易信号
ENGINETYPE_TRADING = 'trading'  # 实盘
ENGINETYPE_QUOTE = 'quote'
ENGINETYPE_MARKET = 'market'
ENGINETYPE_RISK = 'RISK'
ENGINETYPE_DATA = 'DATA'
ENGINETYPE_ACCOUNT = 'ACCOUNT'

HOLDING_TYPE = {'NONE': 0,
                'SINGLE': 1,
                'DOUBLE': 2,
                'LONG': 3,
                'SHORT': 4}
HOLDING_TYPE_NONE = 'NONE'
HOLDING_TYPE_SINGLE = 'SINGLE'
HOLDING_TYPE_DOUBLE = 'DOUBLE'
HOLDING_TYPE_LONG = 'LONG'
HOLDING_TYPE_SHORT = 'SHORT'

# 指标类型
INDICATOR_TYPE_TREND = "TREND"
INDICATOR_TYPE_INV = "INV"
INDICATOR_TYPE_TRACE = "TRACE"

# 变量输出类型
VARIABLE_OUT_TYPE_NONE = "None"
VARIABLE_OUT_TYPE_MAIN = "Main"
VARIABLE_OUT_TYPE_SECOND = "Second"
VARIABLE_OUT_TYPE_WINDOW = "Window"

# 公式类型：指标、策略
FORMULA_TYPE_STRATEGY = 'strategy'  # 交易策略
FORMULA_TYPE_INDICATOR = 'indicator'  # 指标
FORMULA_TYPE_SELECTOR = 'selector'  # 选股方法


# endregion
class TrendClass:
    """价格走势分类"""

    def __init__(self):
        self.balance = 0  # 均衡状态
        self.up = 0  # 上涨
        self.down = 0  # 下跌
        self.balance_start = 0  # 均衡状态开始
        self.up_start = 0  # 上涨开始
        self.down_start = 0  # 下跌开始
        self.balance_ok = 0  # 均衡状态确认
        self.up_ok = 0  # 上涨确认
        self.down_ok = 0  # 下跌确认
        self.balance_end = 0  # 均衡状态结束
        self.up_end = 0  # 上涨结束
        self.down_end = 0  # 下跌结束


# 交易绩效统计结果英汉字典
PERFORMANCE_EN_ZH_DICT = {'period': '周期',  # PERIOD_TYPE_
                          'totalPeriods': '周期数',
                          'holdingPeriods': '持仓周期数',
                          'totalCount': '总交易次数',
                          'totalWinCount': '总盈利次数',
                          'totalLossCount': '总亏损次数',
                          'totalInvest': '总投资',
                          'winInvest': '盈利投资',
                          'lossInvest': '亏损投资',
                          'totalProfit': '总利润',  # totalWin - totalLoss
                          'totalWin': '总盈利',
                          'totalLoss': '总亏损',
                          'totalProfitRate': '总利润率',  # totalProfit/totalInvest
                          'totalWinProfitRate': '总盈利率',  # totalWin/winInvest
                          'totalLossProfitRate': '总亏损率',  # totalLoss/lossInvest
                          'perProfit': '平均每笔利润',  # totalProfit/totalCount
                          'perProfitRate': '平均每笔利润率',  # totalProfitRate/totalCount
                          'maxDrawback': '最大回撤',
                          'perWin': '平均每笔盈利',  # totalWin/totalWinCount
                          'perFee': '平均每笔佣金',  # totalFee/totalCount
                          'perLoss': '平均每笔亏损',  # totalLoss/totalLossCount
                          'winRatio': '胜率',  # totalWinCount/totalCount
                          'winLossRatio': '盈亏比',  # totalWin/totalLoss
                          'annualRate': '年化收益率',
                          'annualTradeTimes': '年均交易次数',  # totalCount
                          'maxWin': '最大盈利',
                          'maxLoss': '最大亏损',
                          'winLastTimes': '最大连续盈利次数',
                          'lossLastTimes': '最大连续亏损次数',
                          'longCount': '多头交易次数',
                          'longWinCount': '多头盈利次数',
                          'longLossCount': '多头亏损次数',
                          'longProfit': '多头利润',
                          'longWin': '多头盈利',
                          'longLoss': '多头亏损',
                          'longProfitRate': '多头利润率',
                          'longWinProfitRate': '多头盈利率',
                          'longLossProfitRate': '多头亏损率',
                          'perLongProfit': '多头平均每笔利润',
                          'perLongProfitRate': '多头平均每笔利润率',
                          'maxLongDrawback': '多头最大回撤',
                          'perLongWin': '平均多头每笔盈利',
                          'perLongFee': '多头平均每笔佣金',
                          'perLongLoss': '多头平均每笔亏损',
                          'winLongRatio': '多头胜率',
                          'winLongLossRatio': '多头盈亏比',
                          'annualLongRate': '多头年化收益率',
                          'annualLongTimes': '多头年均交易次数',
                          'maxLongWin': '多头最大盈利',
                          'maxLongLoss': '多头最大亏损',
                          'winLongLastTimes': '多头最大连续盈利次数',
                          'lossLongLastTimes': '多头最大连续亏损次数',
                          'shortCount': '空头交易次数',
                          'shortWinCount': '空头盈利次数',
                          'shortLossCount': '空头亏损次数',
                          'shortProfit': '空头利润',
                          'shortWin': '空头盈利',
                          'shortLoss': '空头亏损',
                          'shortProfitRate': '空头利润率',
                          'shortWinProfitRate': '空头盈利率',
                          'shortLossProfitRate': '空头亏损率',
                          'perShortProfit': '空头平均每笔利润',
                          'perShortProfitRate': '空头平均每笔利润率',
                          'maxShortDrawback': '空头最大回撤',
                          'perShortWin': '平均空头每笔盈利',
                          'perShortFee': '空头平均每笔佣金',
                          'perShortLoss': '空头平均每笔亏损',
                          'winShortRatio': '空头胜率',
                          'winShortLossRatio': '空头盈亏比',
                          'annualShortRate': '空头年化收益率',
                          'annualShortTimes': '空头年均交易次数',
                          'maxShortWin': '空头最大盈利',
                          'maxShortLoss': '空头最大亏损',
                          'winShortLastTimes': '空头最大连续盈利次数',
                          'lossShortLastTimes': '空头最大连续亏损次数'

                          }


class Direction(Enum):
    """
    Direction of order/trade/position.
    """
    LONG = "多"
    SHORT = "空"
    NET = "净"


class DirectType(Enum):
    """买卖"""
    Buy = 0
    """买"""
    Sell = 1
    """卖"""


class OffsetType(Enum):
    """开平"""
    Open = 0
    '''开'''
    Close = 1
    '''平'''


class Offset(Enum):
    """
    Offset of order/trade.
    """
    NONE = ""
    OPEN = "开"
    CLOSE = "平"
    CLOSETODAY = "平今"
    CLOSEYESTERDAY = "平昨"


class Status(Enum):
    """
    Order status.
    """
    SUBMITTING = "提交中"
    NOTTRADED = "未成交"
    PARTTRADED = "部分成交"
    ALLTRADED = "全部成交"
    CANCELLED = "已撤销"
    REJECTED = "拒单"


class Product(Enum):
    """
    Product class.
    """
    EQUITY = "股票"
    FUTURES = "期货"
    OPTION = "期权"
    INDEX = "指数"
    FOREX = "外汇"
    SPOT = "现货"
    ETF = "ETF"
    BOND = "债券"
    WARRANT = "权证"
    SPREAD = "价差"
    FUND = "基金"


class OrderPriceType(Enum):
    """
    Order type.
    """
    LIMIT = "限价"
    MARKET = "市价"
    STOP = "STOP"
    FAK = "FAK"
    FOK = "FOK"


class OrderType(Enum):
    BUY = '开多'
    SELL = '平多'
    SHORT = '开空'
    COVER = '平空'


class OptionType(Enum):
    """
    Option type.
    """
    CALL = "看涨期权"
    PUT = "看跌期权"


class Exchange(Enum):
    """
    Exchange.
    """
    # Chinese
    CFFEX = "CFFEX"  # China Financial Futures Exchange
    SHFE = "SHFE"  # Shanghai Futures Exchange
    CZCE = "CZCE"  # Zhengzhou Commodity Exchange
    DCE = "DCE"  # Dalian Commodity Exchange
    INE = "INE"  # Shanghai International Energy Exchange
    SSE = "SSE"  # Shanghai Stock Exchange
    SZSE = "SZSE"  # Shenzhen Stock Exchange
    SGE = "SGE"  # Shanghai Gold Exchange
    WXE = "WXE"  # Wuxi Steel Exchange

    # Global
    SMART = "SMART"  # Smart Router for US stocks
    NYMEX = "NYMEX"  # New York Mercantile Exchange
    COMEX = "COMEX"  # a division of theNew York Mercantile Exchange
    GLOBEX = "GLOBEX"  # Globex of CME
    IDEALPRO = "IDEALPRO"  # Forex ECN of Interactive Brokers
    CME = "CME"  # Chicago Mercantile Exchange
    ICE = "ICE"  # Intercontinental Exchange
    SEHK = "SEHK"  # Stock Exchange of Hong Kong
    HKFE = "HKFE"  # Hong Kong Futures Exchange
    SGX = "SGX"  # Singapore Global Exchange
    CBOT = "CBT"  # Chicago Board of Trade
    CBOE = "CBOE"  # Chicago Board Options Exchange
    CFE = "CFE"  # CBOE Futures Exchange
    DME = "DME"  # Dubai Mercantile Exchange
    EUREX = "EUX"  # Eurex Exchange
    APEX = "APEX"  # Asia Pacific Exchange
    LME = "LME"  # London Metal Exchange
    BMD = "BMD"  # Bursa Malaysia Derivatives
    TOCOM = "TOCOM"  # Tokyo Commodity Exchange
    EUNX = "EUNX"  # Euronext Exchange
    KRX = "KRX"  # Korean Exchange

    OANDA = "OANDA"  # oanda.com

    # CryptoCurrency
    BITMEX = "BITMEX"
    OKEX = "OKEX"
    HUOBI = "HUOBI"
    BITFINEX = "BITFINEX"
    BINANCE = "BINANCE"
    BYBIT = "BYBIT"  # bybit.com
    COINBASE = "COINBASE"
    GATEIO = "GATEIO"
    BITSTAMP = "BITSTAMP"

    # Special Function
    LOCAL = "LOCAL"  # For local generated data


class Currency(Enum):
    """
    Currency.
    """
    USD = "USD"
    HKD = "HKD"
    CNY = "CNY"


class Interval(Enum):
    """
    Interval of bar data.
    """
    TICK = 't'
    SECOND = 's'
    MINUTE = "m"
    HOUR = "h"
    DAILY = "d"
    WEEKLY = "W"
    MONTH = 'M'
    QUARTER = 'Q'
    YEAR = 'Y'


INTERVAL_DELTA_MAP = {
    Interval.TICK: timedelta(milliseconds=500),
    Interval.SECOND: timedelta(seconds=1),
    Interval.MINUTE: timedelta(minutes=1),
    Interval.HOUR: timedelta(hours=1),
    Interval.DAILY: timedelta(days=1),
}


class IntervalType(Enum):
    """时间间隔（周期）类型:tick, 秒,分,时,日,周,月,年"""
    Tick = 0

    Second = 1
    '''秒'''

    Minute = Second * 60
    '''分'''

    Hour = Minute * 60
    '''时'''

    Day = Hour * 24
    '''日'''

    Week = Day * 7
    '''周'''

    Month = Day * 30
    '''月'''

    Year = Day * 365
    '''年'''

    @classmethod
    def to_type_int(cls, period_sec: int):
        if period_sec % cls.Year == 0:
            return cls.Year
        elif period_sec % cls.Month == 0:
            return cls.Month
        elif period_sec % cls.Week == 0:
            return cls.Week
        elif period_sec % cls.Day == 0:
            return cls.Day
        elif period_sec % cls.Hour == 0:
            return cls.Hour
        elif period_sec % cls.Minute == 0:
            return cls.Minute
        elif period_sec % cls.Second == 0:
            return cls.Second
        else:
            return cls.Tick

    @classmethod
    def to_interval(cls, period_sec: int) -> Interval:
        nm = cls.to_type_int(period_sec)
        if nm == cls.Year:
            return Interval.YEAR
        elif nm == cls.Month:
            return Interval.MONTH
        elif nm == cls.Week:
            return Interval.WEEKLY
        elif nm == cls.Day:
            return Interval.DAILY
        elif nm == cls.Hour:
            return Interval.HOUR
        elif nm == cls.Minute:
            return Interval.MINUTE
        else:
            return Interval.TICK


period_second_dict = {
    't': 0,
    '1m': 60,
    '3m': 180,
    '5m': 300,
    '10m': 600,
    '15m': 900,
    '30m': 1800,
    '1h': 3600,
    '1d': 86400,
    '1w': 604800,
    'M': 18144000,
    'hy': 108864000,
    'y': 217728000,

}


class Period:
    """周期的定义
    interval_type: IntervalType.Tick，以秒计的周期的时间单位
    interval: Interval.TICK，周期的时间单位
    intervals: int = 1，以秒计的周期间隔，0＝＝Tick
    """
    interval: Interval.TICK = Interval.MINUTE
    interval_type: IntervalType.Tick = IntervalType.Minute
    intervals: int = 60

    @property
    def periods(self):
        """以 interval 计的周期数
        当 self.interval == IntervalType.Tick or self.intervals < self.interval
        时，返回 self.interval ,否则，返回 int(self.intervals / self.interval)
        """
        return self.intervals if self.interval == IntervalType.Tick or self.intervals < self.interval_type else int(
            self.intervals / self.interval_type)


class TypePeriod(Enum):
    TICK = 0
    M1 = 1 * 60
    M3 = 3 * 60
    M5 = 5 * 60
    M10 = 10 * 60
    M15 = 15 * 60
    M30 = 30 * 60
    H1 = 60 * 60
    DAY = 60 * 24 * 60
    WEEK = 60 * 24 * 7 * 60
    MONTH = 60 * 24 * 30 * 60
    YEAR = 60 * 24 * 365 * 60


class StraOrderType(Enum):
    BUY = 1
    SELL = -1
    SHORT = -2
    COVER = 2
    COVER_BUY = 4
    SELL_SHORT = -4


class StraOffsetType(Enum):
    OPEN = 1
    CLOSE = -1
    STOP_LOSS = -2
    STOP_WIN = 2


class StraDirectionType(Enum):
    LONG = 1
    SHORT = -1


class StraOrderTypeCn(Enum):
    BUY = '开多'
    SELL = '平多'
    SHORT = '开空'
    COVER = '平空'
    COVER_BUY = '平空开多'
    SELL_SHORT = '平多开空'


class StraOffsetTypeCn(Enum):
    OPEN = '开'
    CLOSE = '平'
    STOP_LOSS = '止损'
    STOP_WIN = '止赢'


class StraDirectionTypeCn(Enum):
    LONG = '多'
    SHORT = '空'


# 指标类型
INDICATOR_TYPE = {
    'TREND': 1,  # 趋势型
    'INV': 2,  # 反转型
    'TRACE': 3  # 轨道型
}


class IndicatorType(Enum):
    TREND = 1  # 趋势指标
    INV = 2  # 反趋势指标
    TRACE = 3  # 轨道（支撑压力）指标
    VOL = 4  # 成交量指标
    VOLPRICE = 5  # 量价指标
    OCILLATOR = 6  # 振荡指标


# 变量输出类型
VARIABLE_OUT_TYPE = {
    "None": 0,  # 不输出
    "Main": 1,  # 主坐标轴
    "Second": 2,  # 副坐标轴
    "Window": 3  # 由窗口的大小确定
}


class VariableOutType(Enum):
    NONE = 0  # 不输出
    MAIN = 1  # 主坐标轴
    SECOND = 2  # 副坐标轴
    WINDOW = 3  # 由窗口的大小确定


class PriceType(Enum):
    """限价"""
    LIMIT = 0
    """市价"""
    MARKET = 1
    """下一市价"""
    MARKETA = 2
    """开盘价"""
    OPEN = 3
    """收盘价"""
    CLOSE = 4
    """下一市价"""
    BEST = 5
    """下一市价"""
    WORST = 6


class StopOrderStatus(Enum):
    WAITING = "等待中"
    CANCELLED = "已撤销"
    TRIGGERED = "已触发"


class EngineType(Enum):
    LIVE = "实盘"
    BACKTESTING = "回测"
    TEST = "测试"  # 利用实盘行情数据，运行策略，保存策略信号


class BacktestingMode(Enum):
    BAR = 1
    TICK = 0


TickOrBar = BacktestingMode

KDataFrame = pd.DataFrame(columns=['open', 'high', 'low', 'close', 'vol', 'amt', 'datetime'])
